문서의 임의 삭제는 제재 대상으로, 문서를 삭제하려면 삭제 토론을 진행해야 합니다. 문서 보기문서 삭제토론 디자인 패턴 (문단 편집) === 상태(State) === [Include(틀:상세 내용, 문서명=유한 상태 기계)] 객체의 현재 상태에 따라 특정 동작을 시행했을 때 상태를 변환시키거나 다른 행동을 취할 수 있게 허가하는 패턴을 의미한다. 즉 객체 내부에 존재하는 어떠한 '상태'가 존재하며, 같은 행동을 하더라도 상태에 따라 전혀 다른 행동을 취하고, 상황에 따라서는 상태 자체를 변경시키기도 한다. 이러한 변화를 상태 인터페이스에게 맡기고 객체는 하던 대로 행위만 맡기는 패턴이 상태 패턴이다. 전자레인지를 예시로 들어보자. 전자레인지에는 "작동 버튼"과 "취소 버튼"이 있고, "정지 상태", "일시 정지 상태", "작동 상태"라는 세 가지 상태가 있다. 각 상태에 따라 버튼을 누르면 이하와 같은 변화가 나타난다. || || 작동 버튼 || 취소 버튼 || || 정지 상태 || 30초를 추가하고 작동 상태가 됨 || - || || 일시 정지 상태 || 작동 상태가 됨 || 정지 상태가 됨 || || 작동 상태 || 30초를 추가함 (상태 변화 X) || 일시 정지 상태가 됨 || 이를 기본적으로 switch-case 베이스로 코딩하면 이하와 같을 것이다. (디자인 패턴에 대해서만 설명하므로, 편의 상 count가 매 초마다 내려간다든가 count가 0이 되면 정지 상태가 되는 부분 등은 구현하지 않는다.) {{{#!syntax csharp enum OvenState{ default = 0, stop, pause, run } public class micro_oven{ private int ovenCount; private OvenState ovenState; public void onButton(){ switch(ovenState){ case OvenState.stop: ovenState = OvenState.run; ovenCount += 30; break; case OvenState.pause: ovenState = OvenState.run; break; case OvenState.run: ovenCount += 30; break; } } public void offButton(){ switch(ovenState){ case OvenState.stop: break; case OvenState.pause: ovenState = OvenState.stop; break; case OvenState.run: ovenState = OvenState.pause; break; } } } }}} 이 코드 자체는 지금 당장 실행하는 데에는 문제가 없다. 그러나 만약에 추후 전자레인지에 작동, 정지, 일시 정지 외의 다른 상태가 생겨난다면 저 onButton과 offButton의 switch 문을 일일이 수정해야 한다. 이는 추후 유지보수가 정말 귀찮아질뿐더러, 이 class 자체가 '현재 전자레인지의 상태'와 '어떤 버튼을 누름'이라는 두 개의 책임 모두 한 데 들어있어 SRP도 위반한다. 여기서 State 패턴을 활용하여 전자레인지의 작동 방식을 코딩하는 것은 이하와 같다. 1. 각 State에서 공통적으로 사용하는 인터페이스를 만든다. 여기에서는 '정지 버튼'과 '작동 버튼'이 될 것이다. {{{#!syntax csharp interface OvenState{ void onButton(); void offButton(); } }}} 2. 작동 상태, 일시 정지 상태, 정지 상태에 해당하는 state를 각각 만들고, 인터페이스 함수의 동작을 정의할 때 자신이 지정한 오븐의 상태도 변경하게 코딩한다. 여기서 MicroOven이라는 Class는 3번에서 전자레인지의 현 상태를 나타내는 클래스가 될 것이다. {{{#!syntax csharp public class StopState : OvenState{ public MicroOven microOven; public StopState(MicroOven microOven){ this.microOven = microOven; } // 오븐의 상태를 표시해줄 MicroOven을 생성자에 추가 public override void onButton(){ microOven.ovenCount += 30; microOven.ovenState = microOven.RunState; } public override void offButton(){ microOven.ovenState = microOven.StopState; } } public class PauseState : OvenState{ // 생성자는 동일 public override void onButton(){ microOven.ovenState = microOven.RunState; } public override void offButton(){ microOven.ovenState = microOven.StopState; } } public class RunState : OvenState{ // 생성자는 동일 public override void onButton(){ microOven.ovenCount += 30; } public override void offButton(){ microOven.ovenState = microOven.PauseState; } } }}} 3. 전자레인지의 상태(겸 작동 시간)를 나타내는 MicroOven class를 정의해준다. {{{#!syntax csharp public class MicroOven{ public readonly State StopState; public readonly State PauseState; public readonly State RunState; public MicroOven(){ this.StopState = new StopState(this); this.PauseState = new PauseState(this); this.RunState = new RunState(this); } // 각 State를 의미하는 변수를 처음 생성할 때 고정 private State ovenState; private float ovenCount; public void onButton(){ ovenState.onButton(); } public void offButton(){ ovenState.offButton(); } } }}} 이렇게 하면 MicroOven.onButton() 및 MicroOven.offButton() 함수를 호출할 경우 ovenState에 따라 각자 배정된 동작을 해줄뿐더러, ovenState 그 자신을 바꾸는 과정 역시 2번 class에서 해결된다.저장 버튼을 클릭하면 당신이 기여한 내용을 CC-BY-NC-SA 2.0 KR으로 배포하고,기여한 문서에 대한 하이퍼링크나 URL을 이용하여 저작자 표시를 하는 것으로 충분하다는 데 동의하는 것입니다.이 동의는 철회할 수 없습니다.캡챠저장미리보기